/*-----------------------------------------------------------------------------
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License. You may obtain a copy of the License at
	http://www.mozilla.org/MPL/
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
	
	The Original Code is Fever Framework code.
	
	The Initial Developer of the Original Code is Romain Ecarnot.
	Portions created by Initial Developer are Copyright (C) 2006
	the Initial Developer. All Rights Reserved.
	
	Contributor(s):
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
-----------------------------------------------------------------------------*/

import org.aswing.ASWingUtils;
import org.aswing.border.Border;
import org.aswing.border.EmptyBorder;
import org.aswing.border.TitledBorder;
import org.aswing.BorderLayout;
import org.aswing.Component;
import org.aswing.geom.Point;
import org.aswing.Insets;
import org.aswing.JButton;
import org.aswing.JComboBox;
import org.aswing.JFrame;
import org.aswing.JLabel;
import org.aswing.JPanel;
import org.aswing.SoftBoxLayout;
import org.aswing.UIManager;

import fever.app.theme.Theme;
import fever.app.theme.ThemeLocator;
import fever.display.ModalScreen;
import fever.Fever;

import fvaswing.components.FvBitmapIcon;
import fvaswing.components.themechooser.FvThemeChooserResources;

/**
 * Chooser dialog to customize application Look and Feel.
 * 
 * <p>Dialog is open in modal mode to avoid user interactions during 
 * customisation process.
 * 
 * <p>Modifications can be process at runtime or at application restart<br />
 * Using a SharedLocal object saved object.
 * 
 * <p>Use {@link #enabledRuntimeSwapping} property to define if runtime is enabled 
 * or not.
 * 
 * <p>Take a look at {@link fever.app.theme.Theme} class to know how 
 * to register AsWing Look'nFeel.
 * 
 * <p>Register some themes :
 * {@code
 *   var at : ThemeLocator = ThemeLocator.getInstance();
 *   at.register( 'Office 2003', new Office2003LAF() );
 *   at.register( 'WinXP 2003', new WinXPLAF() );
 *   at.addEventListener( FvThemeLocator.onChangeEVENT, this, _onUIUpdate );
 *   at.load( 'WinXP 2003' );
 * }
 * 
 * <p>Opens chooser
 * {@code
 *   FvThemeChooser.open();
 * }
 * 
 * @author Romain Ecarnot
 */
class fvaswing.components.FvThemeChooser
{
	//-------------------------------------------------------------------------
	// Private properties
	//-------------------------------------------------------------------------
	
	private static var _instance : FvThemeChooser;	
	private var _frame : JFrame;
	private var _list : JComboBox;
	private var _preview : JLabel;
	private var _okButton : JButton;
	private var _cancelButton : JButton;
	private var _applyButton : JButton;
	private var _restartLabel : JLabel;
	private var _modal : ModalScreen;
	
	private var _previewPanel : JPanel;
	private var _themePanel : JPanel;
	
	private var _current : Theme;
	private var _testedTheme : String;
	
	
	//-------------------------------------------------------------------------
	// Public Properties
	//-------------------------------------------------------------------------
	
	/** 
	 * Indicates if theme can be apply at runtime or only at application 
	 * restart. Default is {@code true}.
	 */
	public static var  enabledRuntimeSwapping : Boolean = true;
	
	
	//-------------------------------------------------------------------------
	// Public API
	//-------------------------------------------------------------------------
	
	/**
	 * Retreives singleton instance.
	 */
	public static function getInstance(  ) : FvThemeChooser
	{
		if( !_instance ) _instance = new FvThemeChooser();
		return _instance;
	}
	
	/**
	 * Opens dialog.
	 */
	public function open() : Void
	{
		_openDialog();
	}
	
	
	//-------------------------------------------------------------------------
	// Private implementation
	//-------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	private function FvThemeChooser()
	{
		_configureUI();
	}
	
	/**
	 * Resets JList data and open dialog.
	 */
	private function _openDialog() : Void
	{
		_current  = ThemeLocator.getInstance().getCurrentTheme();
		
		if( !_current )
		{
			_current = new Theme( 'default', UIManager.getLookAndFeel() );
			ThemeLocator.getInstance().registerTheme( _current );
		}
		
		_testedTheme = _current.getName();
		
		_list.setListData( ThemeLocator.getInstance().getThemeList() );
		_list.setSelectedItem( _current.getName() );
		_list.revalidateIfNecessary();
		
		_updateLocalisation();
		
		_restartLabel.setVisible( !enabledRuntimeSwapping );
		
		_layout();
		_modal.show();
		_frame.show();
	}
	
	private function _updateLocalisation() : Void
	{
		_okButton.setText( FvThemeChooserResources.getInstance().okLabel );
		_cancelButton.setText( FvThemeChooserResources.getInstance().cancelLabel );
		_applyButton.setText( FvThemeChooserResources.getInstance().applyLabel );
		_restartLabel.setText( FvThemeChooserResources.getInstance().restartMessage );
		_frame.setTitle(  FvThemeChooserResources.getInstance().title );
		_themePanel.setBorder( _buildTiledBorder( FvThemeChooserResources.getInstance().lafTitle ) );		_previewPanel.setBorder( _buildTiledBorder( FvThemeChooserResources.getInstance().previewTitle ) );
	}
	
	/**
	 * Prepares dialog.
	 */
	private function _configureUI() : Void
	{
		_configureBasedFrame();
		
		_themePanel = _buildTiledPanel( '' );
		_themePanel.append( _getLafList(), BorderLayout.NORTH );
		
		_previewPanel = _buildTiledPanel( '' );
		_previewPanel.append( _getPreview(), BorderLayout.NORTH );
		
		_restartLabel = new JLabel( '' );
		
		var option : JPanel = new JPanel( new SoftBoxLayout( SoftBoxLayout.Y_AXIS, 5 ) );
		option.append( _themePanel );		option.append( _previewPanel );
		option.append( _restartLabel );
		
		var framePanel : JPanel = new JPanel( new BorderLayout( 5, 5 ) );
		framePanel.setBorder( new EmptyBorder( null, new Insets( 5, 5, 5, 5 ) ) );
		framePanel.append( option, BorderLayout.NORTH );
		framePanel.append( _getButtonPanel(), BorderLayout.SOUTH );
		
		_frame.getContentPane().append ( framePanel, BorderLayout.CENTER );
	}
	
	/**
	 * Configures the based {@code JFrame} container.
	 */
	private function _configureBasedFrame() : Void
	{
		_modal = new ModalScreen();
		
		_frame = new JFrame( _modal.getModalTarget(), '', false );
		_frame.setResizable( false );
		_frame.setClosable( false );
		_frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
		_frame.addEventListener( JFrame.ON_WINDOW_CLOSING, _handleClose, this );
	}
	
	/**
	 * Creates LAF Chooser list
	 */
	private function _getLafList() : JComboBox
	{
		_list = new JComboBox(  );
		_list.addActionListener( _handleListClick, this );
		return _list;	
	}
	
	/**
	 * Creates container for laf preview image
	 */
	private function _getPreview() : Component
	{
		_preview = new JLabel( '', JLabel.CENTER );
		_preview.setPreferredSize( 250, 150 );
		
		return _preview;
	}
	
	private function _getButtonPanel() : JPanel
	{
		var w : Number = 100;
		
		_okButton = new JButton( '-' );
		_okButton.setPreferredWidth( w );
		_okButton.addActionListener( _handleOkButton, this );
		
		_cancelButton = new JButton( '-' );
		_cancelButton.setPreferredWidth( w );
		_cancelButton.addActionListener( _handleCancelButton, this );
		
		_applyButton = new JButton( '-' );
		_applyButton.setPreferredWidth( w );
		_applyButton.addActionListener( _handleApply, this );
		 
		var p : JPanel = new JPanel( new SoftBoxLayout( SoftBoxLayout.X_AXIS, 5, SoftBoxLayout.RIGHT ) );
		p.append( _okButton );
		p.append( _cancelButton );
		p.append( _applyButton );
		return p;
	}
	
	/**
	 * Calculates a new frame position
	 */
	private function _layout() : Void
	{
		_frame.pack();
		
		var location : Point = ASWingUtils.getScreenCenterPosition();
		location.x = _frame.getWidth()/2;
		location.y = _frame.getHeight()/2;
		_frame.setLocation( location );
	}
	
	/**
	 * Creates a new JPanel with TiledBorder
	 */
	private function _buildTiledPanel( caption ) : JPanel
	{
		var p : JPanel = new JPanel( new BorderLayout( 5, 5 ) );
		p.setBorder( _buildTiledBorder( caption ) );
		return p;
	}
	
	/**
	 * Creates a tiled border.
	 */
	private function _buildTiledBorder( caption : String ) : Border
	{
		return new TitledBorder( _buildInternalBorder(), caption, TitledBorder.TOP, TitledBorder.LEFT, 10 );	
	}
	
	/**
	 * Creates internal border on component
	 */
	private function _buildInternalBorder() : Border
	{
		return 	new EmptyBorder( null, new Insets( 0,10,5,10 ) );
	}
	
	/**
	 * Trigerred when user click on a button ( or default close button )
	 */
	private function _handleClose( button : JButton ) : Void
	{
		_modal.hide();
		_frame.tryToClose();
	}
	
	/**
	 * Triggered when user click on list's item.
	 */
	private function _handleListClick( source : JComboBox ) : Void
	{
		var theme : Theme = ThemeLocator.getInstance().getTheme( source.getSelectedItem().toString() );
		
		if( theme.hasPreview() )
		{
			_preview.setText( );	
			_preview.setIcon( FvBitmapIcon.create( theme.getPreview(), Theme.PREVIEW_REPOSITORY ) );
		}
		else
		{
			_preview.setIcon( null );
			_preview.setText( FvThemeChooserResources.getInstance().noPreviewLabel );	
		}
	}

	private function _handleCancelButton() : Void
	{
		_applySelectedTheme( _current );
		_handleClose();
	}

	private function _handleOkButton() : Void
	{
		if( !enabledRuntimeSwapping )
		{
			_saveCookie( _list.getSelectedItem().toString() );
		}
		_handleClose();
	}

	private function _handleApply() : Void
	{
		if( enabledRuntimeSwapping )
			_applySelectedTheme( ThemeLocator.getInstance().getTheme( _list.getSelectedItem().toString() ) );
	}
	
	private function _applySelectedTheme ( theme : Theme ) : Void
	{
		if( ( _testedTheme != theme.getName() ) )
		{
			_testedTheme = theme.getName();
			ThemeLocator.getInstance().load( theme.getName() );
		}
	}
	
	private function _saveCookie( lafName : String ) : Void
	{
		Fever.application.config.save( ThemeLocator.CONFIG_ID, lafName );
	}
}